﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;

namespace NetTopologySuite.Triangulate
{
	public class SplitSegment
	{
		private static Coordinate PointAlongReverse(LineSegment seg, double segmentLengthFraction)
		{
			return new Coordinate
			{
				X = seg.P1.X - segmentLengthFraction * (seg.P1.X - seg.P0.X),
				Y = seg.P1.Y - segmentLengthFraction * (seg.P1.Y - seg.P0.Y)
			};
		}

		public SplitSegment(LineSegment seg)
		{
			this._seg = seg;
			this._segLen = seg.Length;
		}

		public double MinimumLength
		{
			get
			{
				return this._minimumLen;
			}
			set
			{
				this._minimumLen = value;
			}
		}

		public Coordinate SplitPoint
		{
			get
			{
				return this._splitPt;
			}
		}

		public void SplitAt(double length, Coordinate endPt)
		{
			double segmentLengthFraction = this.GetConstrainedLength(length) / this._segLen;
			if (endPt.Equals2D(this._seg.P0))
			{
				this._splitPt = this._seg.PointAlong(segmentLengthFraction);
				return;
			}
			this._splitPt = SplitSegment.PointAlongReverse(this._seg, segmentLengthFraction);
		}

		public void SplitAt(Coordinate pt)
		{
			double segmentLengthFraction = this._minimumLen / this._segLen;
			if (pt.Distance(this._seg.P0) < this._minimumLen)
			{
				this._splitPt = this._seg.PointAlong(segmentLengthFraction);
				return;
			}
			if (pt.Distance(this._seg.P1) < this._minimumLen)
			{
				this._splitPt = SplitSegment.PointAlongReverse(this._seg, segmentLengthFraction);
				return;
			}
			this._splitPt = pt;
		}

		private double GetConstrainedLength(double len)
		{
			if (len < this._minimumLen)
			{
				return this._minimumLen;
			}
			return len;
		}

		private readonly LineSegment _seg;

		private readonly double _segLen;

		private Coordinate _splitPt;

		private double _minimumLen;
	}
}
